/*
 * Copyright (C) 2021 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the
 *       distribution.
 *    3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of
 *       its contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#ifndef __XR_WIFI_ADAPTER_H__
#define __XR_WIFI_ADAPTER_H__

#include <stdlib.h>
#include "net_ctrl.h"
#include "sys_ctrl/sys_ctrl.h"
#include "sysinfo.h"
#include "net/wlan/wlan_defs.h"
#include "net/wlan/wlan.h"

#define XR_WIFI_LOG_LEVEL 3
#if 1
#define XR_WIFI_LOG(format, ...) printf(format, ##__VA_ARGS__)
#endif
#define XR_WIFI_DBG(msg, ...)                                                  \
	do {                                                                   \
		if (XR_WIFI_LOG_LEVEL > 2)                                     \
			XR_WIFI_LOG("[xr wifi] " msg, ##__VA_ARGS__);          \
	} while (0)
#define XR_WIFI_WAR(msg, ...)                                                  \
	do {                                                                   \
		if (XR_WIFI_LOG_LEVEL > 1)                                     \
			XR_WIFI_LOG("[xr wifi] WAR " msg, ##__VA_ARGS__);      \
	} while (0)
#define XR_WIFI_ERR(msg, ...)                                                  \
	do {                                                                   \
		if (XR_WIFI_LOG_LEVEL > 0)                                     \
			XR_WIFI_LOG("[xr wifi] ERR " msg, ##__VA_ARGS__);      \
	} while (0)

#define XR_WIFI_OK 0
#define XR_WIFI_FAIL -1

#define XR_WIFI_MAX_SSID_LEN WLAN_SSID_MAX_LEN
#define XR_WIFI_MAX_KEY_LEN WLAN_PSK_HEX_STR_LEN
#define XR_WIFI_AP_KEY_LEN WLAN_PSK_HEX_STR_LEN
#define XR_WIFI_STA_PSK_LEN WLAN_PSK_HEX_LEN
#define XR_WIFI_MAX_AP_STA_NUM 5
#define XR_WIFI_INVALID_CHANNEL 0xff
#define XR_WIFI_WEP40_ASCII_LEN WLAN_WEP40_KEY_LEN
#define XR_WIFI_WEP40_HEX_LEN (WLAN_WEP40_KEY_LEN * 2)
#define XR_WIFI_WEP104_ASCII_LEN WLAN_WEP104_KEY_LEN
#define XR_WIFI_WEP104_HEX_LEN (WLAN_WEP104_KEY_LEN * 2)

#define WIFI_MAC_ADDR_LEN IEEE80211_ADDR_LEN
#define WIFI_MAC_ADDR_EQ(a1, a2) (memcmp(a1, a2, WIFI_MAC_ADDR_LEN) == 0)
#define WIFI_MAC_ADDR_COPY(dst, src) memcpy(dst, src, WIFI_MAC_ADDR_LEN)

#define WIFI_IFNAME_MAX_SIZE 16
#define WIFI_SET_AP_IFNAME(ifname, len)                                        \
	do {                                                                   \
		ifname[0] = 'a';                                               \
		ifname[1] = 'p';                                               \
		ifname[2] = '\0';                                              \
		*len = 2;                                                      \
	} while (0)
#define WIFI_SET_STA_IFNAME(ifname, len)                                       \
	do {                                                                   \
		ifname[0] = 's';                                               \
		ifname[1] = 't';                                               \
		ifname[2] = 'a';                                               \
		ifname[3] = '\0';                                              \
		*len = 3;                                                      \
	} while (0)

typedef enum {
	XR_WIFI_DISCONNECTED,
	XR_WIFI_CONNECTED,
} xr_wifi_conn_status;

typedef struct {
	char ssid[XR_WIFI_MAX_SSID_LEN + 1];
	unsigned char bssid[WIFI_MAC_ADDR_LEN];
	unsigned int channel;
	xr_wifi_conn_status status;
} xr_wifi_status;

int xr_wifi_sta_get_connect_info(xr_wifi_status *connect_status);

typedef enum {
	XR_WIFI_SECURITY_OPEN,
	XR_WIFI_SECURITY_WEP,
	XR_WIFI_SECURITY_WPA2PSK,
	XR_WIFI_SECURITY_WPAPSK_WPA2PSK_MIX,
	XR_WIFI_SECURITY_WPAPSK,
	XR_WIFI_SECURITY_WPA,
	XR_WIFI_SECURITY_WPA2,
	XR_WIFI_SECURITY_SAE,
	XR_WIFI_SECURITY_UNKNOWN
} xr_wifi_auth_mode;

typedef enum {
	XR_WIFI_PARIWISE_UNKNOWN,
	XR_WIFI_PAIRWISE_AES,
	XR_WIFI_PAIRWISE_TKIP,
	XR_WIFI_PAIRWISE_TKIP_AES_MIX
} xr_wifi_pairwise;

typedef struct {
	char ssid[XR_WIFI_MAX_SSID_LEN + 1];
	char key[XR_WIFI_AP_KEY_LEN + 1];
	unsigned char channel_num;
	int ssid_hidden;
	xr_wifi_auth_mode authmode;
	xr_wifi_pairwise pairwise;
} xr_wifi_softap_config;

int xr_wifi_softap_start(xr_wifi_softap_config *conf, char *ifname, int *len);
int xr_wifi_softap_stop(void);

typedef struct {
	unsigned char mac[WIFI_MAC_ADDR_LEN];
} xr_wifi_ap_sta_info;

int xr_wifi_softap_get_connected_sta(xr_wifi_ap_sta_info *sta_list,
				     uint32_t *sta_num);
int xr_wifi_get_channel(const char *ifname, unsigned char ifname_len);
int xr_wifi_sta_start(char *ifname, int *len);
int xr_wifi_sta_set_reconnect_policy(int enable, uint32_t seconds,
				     uint32_t period, uint32_t max_try_count);
int xr_wifi_sta_stop(void);

typedef struct {
	char ssid[XR_WIFI_MAX_SSID_LEN + 1];
	xr_wifi_auth_mode auth;
	char key[XR_WIFI_MAX_KEY_LEN + 1];
	unsigned char bssid[WIFI_MAC_ADDR_LEN];
	xr_wifi_pairwise pairwise;
} xr_wifi_assoc_request;

int xr_wifi_sta_connect(xr_wifi_assoc_request *req);

typedef enum {
	XR_WIFI_WPA_PSK_NOT_USE,
	XR_WIFI_WPA_PSK_USE_INNER,
	XR_WIFI_WPA_PSK_USE_OUTER,
} xr_wifi_wpa_psk_usage_type;

typedef struct {
	xr_wifi_assoc_request req;
	unsigned char channel;
	unsigned char psk[XR_WIFI_STA_PSK_LEN];
	xr_wifi_wpa_psk_usage_type psk_flag;
} xr_wifi_fast_assoc_request;

int xr_wifi_sta_fast_connect(xr_wifi_fast_assoc_request *fast_request);

typedef struct {
	char ssid[XR_WIFI_MAX_SSID_LEN + 1];
	unsigned char bssid[WIFI_MAC_ADDR_LEN];
	unsigned int channel;
	xr_wifi_auth_mode auth;
	int rssi;
	unsigned char wps_flag : 1;
	unsigned char wps_session : 1;
	unsigned char wmm : 1;
	unsigned char resv : 1;
	unsigned char XR_WIFI_mesh_flag : 1;
} xr_wifi_ap_info;

int xr_wifi_sta_scan(void);
int xr_wifi_sta_disconnect(void);
int xr_wifi_sta_scan_results(xr_wifi_ap_info *ap_list, uint8_t *ap_num);
int xr_wifi_sta_get_ap_rssi(void);
void xr_wifi_sta_record_ap_rssi(int rssi);
int xr_wifi_get_macaddr(char *mac_addr, uint8_t mac_len);

typedef enum {
	XR_WIFI_EVT_UNKNOWN,
	XR_WIFI_EVT_SCAN_DONE,
	XR_WIFI_EVT_CONNECTED,
	XR_WIFI_EVT_DISCONNECTED,
	XR_WIFI_EVT_WPS_TIMEOUT,
	XR_WIFI_EVT_MESH_CONNECTED,
	XR_WIFI_EVT_MESH_DISCONNECTED,
	XR_WIFI_EVT_AP_START,
	XR_WIFI_EVT_STA_CONNECTED,
	XR_WIFI_EVT_STA_DISCONNECTED,
	XR_WIFI_EVT_STA_FCON_NO_NETWORK,
	XR_WIFI_EVT_MESH_CANNOT_FOUND,
	XR_WIFI_EVT_MESH_SCAN_DONE,
	XR_WIFI_EVT_MESH_STA_SCAN_DONE,
	XR_WIFI_EVT_AP_SCAN_DONE,
	XR_WIFI_EVT_BUTT
} xr_wifi_event_type;

typedef struct {
	unsigned short bss_num;
} event_wifi_scan_done;

typedef struct {
	char ssid[XR_WIFI_MAX_SSID_LEN + 1];
	unsigned char bssid[WIFI_MAC_ADDR_LEN];
	unsigned char ssid_len;
	char ifname[WIFI_IFNAME_MAX_SIZE + 1];
} event_wifi_connected;

typedef struct {
	unsigned char bssid[WIFI_MAC_ADDR_LEN];
	unsigned short reason_code;
	char ifname[WIFI_IFNAME_MAX_SIZE + 1];
} event_wifi_disconnected;

typedef struct {
	char addr[WIFI_MAC_ADDR_LEN];
} event_ap_sta_connected;

typedef struct {
	unsigned char addr[WIFI_MAC_ADDR_LEN];
	unsigned short reason_code;
} event_ap_sta_disconnected;

typedef struct {
	unsigned char addr[WIFI_MAC_ADDR_LEN];
} event_mesh_connected;

typedef struct {
	unsigned char addr[WIFI_MAC_ADDR_LEN];
	unsigned short reason_code;
} event_mesh_disconnected;

typedef union {
	event_wifi_scan_done wifi_scan_done;
	event_wifi_connected wifi_connected;
	event_wifi_disconnected wifi_disconnected;
	event_ap_sta_connected ap_sta_connected;
	event_ap_sta_disconnected ap_sta_disconnected;
	event_mesh_connected mesh_connected;
	event_mesh_disconnected mesh_disconnected;
} xr_wifi_event_info;

typedef struct {
	xr_wifi_event_type event;
	xr_wifi_event_info info;
} xr_wifi_event;

typedef void (*xr_wifi_event_cb)(const xr_wifi_event *event);

int xr_wifi_register_event_callback(xr_wifi_event_cb event_cb);
int xr_wifi_config_callback(uint8_t mode, uint8_t task_prio,
			    uint8_t stack_size);
int xr_wifi_event_oberser_create();

typedef enum {
	XR_WIFI_BASIC_SCAN,
	XR_WIFI_CHANNEL_SCAN,
	XR_WIFI_SSID_SCAN,
	//XR_WIFI_SSID_PREFIX_SCAN,
	XR_WIFI_BSSID_SCAN,
} xr_wifi_scan_type;

typedef struct {
	char ssid[XR_WIFI_MAX_SSID_LEN + 1];
	unsigned char bssid[WIFI_MAC_ADDR_LEN];
	unsigned char ssid_len;
	unsigned char channel;
	xr_wifi_scan_type scan_type;
} xr_wifi_scan_params;

int xr_wifi_sta_advance_scan(xr_wifi_scan_params *sp);

int xr_wifi_get_local_ip(const char *netif_name, int *const ip);
void xr_wifi_set_local_ip(const char *netif_name, int gw, int ipaddr,
			  int netmask);
void xr_wifi_set_dns_server(int pos, int dns_server);
void xr_wifi_dhcp_enable(const char *netif_name, int enable);
void xr_wifi_netif_status_set(const char *netif_name, int up);

#endif /*__XR_WIFI_ADAPTER_H__*/
